﻿using Infrastructure;
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.DataCollection.Model;
using ZR.DataCollection.OperationCore.OperationEnum;
using ZR.DataCollection.OperationCore.OperationHelper;
using ZR.Model.Models.ProductionControl;
using ZR.Service.Business.IBusinessService;
using ZR.Service.IService.ProductionControl;
using ZR.Service.Service.ProductionControl;
using ZR.ServiceCore.Signalr;

namespace ZR.DataCollection.OperationCore.OperationMode.OP20
{
    public class DaveSaveOP20 : OperationInfoBase
    {
        public override event Action<string> Event_Notification;

        private readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
        private readonly IHubContext<MessageHub> _hubContext = App.GetRequiredService<IHubContext<MessageHub>>();
        private readonly IStationWorkInfoService _stationWorkInfoService = App.GetRequiredService<IStationWorkInfoService>();
        private readonly IBatchBindingService _batchBindingService = App.GetRequiredService<IBatchBindingService>();
        private readonly IOrderDetailInfoService _orderDetailInfoService = App.GetRequiredService<IOrderDetailInfoService>();
        private readonly IMaterialRuleConfigService _materialRuleConfigService = App.GetRequiredService<IMaterialRuleConfigService>();
        private readonly IScanInfoService _scanInfoService = App.GetRequiredService<IScanInfoService>();
        private int collectStatus = 1;

        public DaveSaveOP20(int operationType, string stationType) : base(operationType, stationType)
        {
        }

        public override void WorkDetail(ImpParameter imp)
        {
            DataDock? dataDock = imp.objectParam as DataDock;
            var keyValuePairs = CurrentCruxPoint(dataDock.LineCode, dataDock.ProductType, dataDock.ItemNo);
            SpotHandle(imp, keyValuePairs);
        }

        public override void SpotHandle(ImpParameter parameter, Dictionary<int, List<OperationPointConfig>> SpotGroup)
        {
            try
            {
                foreach (var SpotInfo in SpotGroup)
                {
                    switch (SpotInfo.Key)
                    {
                        case (int)DataOperateEnum.Read:
                            ReadFunction(parameter, SpotInfo.Value);
                            break;

                        case (int)DataOperateEnum.Write:
                            SpotInfo.Value.ForEach(x =>
                            {
                                if (collectStatus.Equals(1))
                                {
                                    parameter.PLCDetail.WriteValue(x.ItemNo, Convert.ToInt16(collectStatus));
                                    _hubContext.Clients.All.SendAsync($"OP20Result", "结果OK");
                                }
                                if (collectStatus.Equals(2))
                                {
                                    parameter.PLCDetail.WriteValue(x.ItemNo, Convert.ToInt16(collectStatus));
                                    _hubContext.Clients.All.SendAsync($"OP20Result", "结果NG");
                                }
                            });
                            break;

                        case (int)DataOperateEnum.Verify:
                            break;

                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Error("数据保存Error", ex);
            }
        }

        private async void ReadFunction(ImpParameter parameter, List<OperationPointConfig> operationPointList)
        {
            DataDock? dataDock = parameter.objectParam as DataDock;
            List<OperationPointConfig> operationPointInfo = operationPointList.FindAll(f => f.GroupName.Equals("0"));
            //产品条码
            string? productId = parameter.PLCDetail.ReadValue(operationPointInfo[0].ItemNo).ToString();
            //批次通道号
            string? thoroughfareNo = parameter.PLCDetail.ReadValue(operationPointInfo[1].ItemNo).ToString();

            Dictionary<string, List<OperationPointConfig>> sortedGroupedDictionary = operationPointList
                                                                                     .GroupBy(gb => gb.GroupName)
                                                                                     .ToDictionary(g => g.Key, g => g.OrderBy(op => op.ItemSort).ToList());
            foreach (var operationPointGroup in sortedGroupedDictionary)
            {
                if (operationPointGroup.Key.Equals("1"))
                {
                    for (int i = 0; i < operationPointGroup.Value.Count; i++)
                    {
                    }
                }
            }
            string productResut = collectStatus.Equals(1) ? "OK" : "NG";
            bool workEnd = await OverStationEnd(dataDock, productId, productResut);
            if (!workEnd)
            {
                collectStatus = 2;
                return;
            }
            OrderDetailInfo orderDetail = await _orderDetailInfoService.QueryByClauseAsync(qbc => qbc.ProductId.Equals(productId));
            BatchBinding batchDetail = await _batchBindingService.QueryByClauseAsync(qbc => qbc.BatchNo.Equals(thoroughfareNo));
            MaterialRuleConfig materialRuleInfo = await _materialRuleConfigService.QueryByClauseAsync(qbc => batchDetail.BatchCode.StartsWith(qbc.MaterialCode));
            _ = SaveBatchCode(dataDock, orderDetail, batchDetail, materialRuleInfo, productId);
        }

        /// <summary>
        /// 条码保存
        /// </summary>
        /// <param name="dataDock"></param>
        /// <param name="productId"></param>
        /// <param name="materialNo"></param>
        /// <returns></returns>
        private async Task<int> SaveBatchCode(DataDock dataDock, OrderDetailInfo orderDetail, BatchBinding batchDetail, MaterialRuleConfig materialRuleInfo, string productId)
        {
            ScanInfo scanInfo = new ScanInfo();
            scanInfo.LineCode = dataDock.LineCode;
            scanInfo.StationCode = dataDock.StationCode;
            scanInfo.OrderCode = orderDetail.OrderCode;
            scanInfo.ProductId = productId;
            scanInfo.ProductType = orderDetail.ProductType;
            scanInfo.MaterialCode = materialRuleInfo.MaterialCode;
            scanInfo.MaterialName = materialRuleInfo.MaterialName;
            scanInfo.MaterialSn = batchDetail.BatchCode;
            scanInfo.CreationTime = DateTime.Now;
            return await _scanInfoService.InsertAsync(scanInfo);
        }
    }
}